home *** CD-ROM | disk | FTP | other *** search
- /*
- File: Track.c
-
- Contains: Contains code to create our rollercoaster track
-
- Written by: Scott Kuechle, based on original Gerbils code by Brian Greenstone
-
- Copyright: © 1998 by Apple Computer, Inc. All rights reserved
-
- Change History (most recent first)
-
- <2> 9/28/98 rtm made changes for Metrowerks compiler
- <1> 9/01/98 srk first file
-
-
- */
-
- /************************************************************
- * *
- * INCLUDE FILES *
- * *
- *************************************************************/
-
- #include "Track.h"
-
-
- /************************************************************
- * *
- * FUNCTION PROTOTYPES *
- * *
- *************************************************************/
-
- static float Track_AmountToRotateNubs(TrackSectionType *trackSectionList,
- long numTrackSections,
- NubEntryType *coordPtr,
- long numNubsInPart,
- long sectionNum,
- float *scale);
- static void Track_PutCameraOnTrack(TQ3CameraObject camera,
- NubEntryType *splinePtArray,
- long numSplinePoints,
- long curTrackLocation);
-
- #if TARGET_OS_WIN32
-
- HANDLE WinIO_CreateFile();
- BOOL WinIO_WriteToFile(HANDLE fileHndl, PartType *thisPart);
-
- #endif
-
-
- /************************************************************
- * *
- * FUNCTION: Track_MakeRandomTrack *
- * *
- * PURPOSE: Generates a random series of track sections *
- * *
- *************************************************************/
-
-
- void Track_MakeRandomTrack(TrackSectionType *trackSectionList,
- long numTrackSections)
- {
- long i,r;
-
- for (i = 0; i < numTrackSections; i++)
- {
- do
- {
- r = Utils_MyRandomLong() & numTrackSections;
- } while(r==7);
-
- trackSectionList[i].partNum = i;
- trackSectionList[i].nubCoord.y = 0;
- trackSectionList[i].nubCoord.x = sin(6.24F/numTrackSections*(float)i)*(LAZY_SUSAN_RADIUS - 6.0F);
- trackSectionList[i].nubCoord.z = cos(6.24F/numTrackSections*(float)i)*(LAZY_SUSAN_RADIUS - 6.0F);
- }
-
- }
-
- /************************************************************
- * *
- * FUNCTION: Track_CreateMasterNubList *
- * *
- * PURPOSE: creates a master list of spline nubs which *
- * contains all of the nubs within all *
- * sections of a track *
- * *
- *************************************************************/
-
- void Track_CreateMasterNubList(TrackSectionType *trackSectionList,
- unsigned long numTrackSections,
- PartType *partsList,
- NubEntryType *nubList,
- long *nubTotal)
- {
- unsigned long sectionNum,partNum,i,numNubsInPart;
- NubEntryType *coordPtr;
- TQ3Point3D sectionStartCoords,basePt,upPt;
- float rotation,scale;
-
- *nubTotal = 0;
-
- for (sectionNum=0; sectionNum < numTrackSections; sectionNum++)
- {
- partNum = trackSectionList[sectionNum].partNum; /* get part # to add */
-
- /* GET INFO FOR PART */
-
- sectionStartCoords = trackSectionList[sectionNum].nubCoord; /* get coords where track section should start */
- numNubsInPart = partsList[partNum].numNubs; /* get # nubs in part */
- coordPtr = partsList[partNum].coordsPtr; /* get ptr to coord list */
-
- rotation = Track_AmountToRotateNubs(trackSectionList,
- numTrackSections,
- coordPtr,
- numNubsInPart,
- sectionNum,
- &scale);
-
- /* COPY & ADJUST PART NUBS */
-
- for (i=1; i < (numNubsInPart-1); i++) /* skip nub 0 & last nub */
- {
-
- basePt = coordPtr->basePt; /* get coords from part data */
- upPt = coordPtr->upPt;
-
- Utils_RotatePoint(&basePt,rotation); /* rotate the points into position */
- Utils_RotatePoint(&upPt,rotation);
-
- basePt.x *= scale; basePt.y *= scale; basePt.z *= scale; /* scale it */
- upPt.x *= scale; upPt.y *= scale; upPt.z *= scale;
-
- nubList[*nubTotal].basePt.x = basePt.x + sectionStartCoords.x; /* tag nubs to end of previous part */
- nubList[*nubTotal].basePt.y = basePt.y + sectionStartCoords.y;
- nubList[*nubTotal].basePt.z = basePt.z + sectionStartCoords.z;
-
-
- nubList[*nubTotal].upPt.x = upPt.x + sectionStartCoords.x;
- nubList[*nubTotal].upPt.y = upPt.y + sectionStartCoords.y;
- nubList[*nubTotal].upPt.z = upPt.z + sectionStartCoords.z;
-
-
- nubList[*nubTotal].sectionNum = sectionNum; /* remember which section this belongs to */
-
-
- coordPtr++;
- (*nubTotal)++;
- }
- }
-
- /* CREATE 3 FINAL NUBS WHICH WRAP BACK TO BEGINNING TO CLOSE THE LOOP */
-
- partNum = trackSectionList[0].partNum; /* get part # */
- coordPtr = partsList[partNum].coordsPtr; /* point back to beginning */
- sectionStartCoords = trackSectionList[0].nubCoord; /* get coords where track section should start */
- numNubsInPart = partsList[partNum].numNubs; /* get # nubs in part */
-
- rotation = Track_AmountToRotateNubs(trackSectionList,
- numTrackSections,
- coordPtr,
- numNubsInPart,
- 0,
- &scale);
-
- for (i=0; i < 3; i++)
- {
- basePt = coordPtr->basePt; /* get coords from part data */
- upPt = coordPtr->upPt;
-
- Utils_RotatePoint(&basePt,rotation); /* rotate the points into position */
- Utils_RotatePoint(&upPt,rotation);
-
- basePt.x *= scale; basePt.y *= scale; basePt.z *= scale; /* scale it */
- upPt.x *= scale; upPt.y *= scale; upPt.z *= scale;
-
- nubList[*nubTotal].basePt.x = basePt.x + sectionStartCoords.x; /* tag nubs to end of previous part */
- nubList[*nubTotal].basePt.y = basePt.y + sectionStartCoords.y;
- nubList[*nubTotal].basePt.z = basePt.z + sectionStartCoords.z;
-
-
- nubList[*nubTotal].upPt.x = upPt.x + sectionStartCoords.x;
- nubList[*nubTotal].upPt.y = upPt.y + sectionStartCoords.y;
- nubList[*nubTotal].upPt.z = upPt.z + sectionStartCoords.z;
-
-
- (*nubTotal)++;
- coordPtr++;
- }
-
- }
-
- /************************************************************
- * *
- * FUNCTION: Track_AmountToRotateNubs *
- * *
- * PURPOSE: Calculates the amount to rotate nubs on the *
- * y axis so that the track section will go *
- * from point A to point B. It also returns a *
- * scaling value used to scale the nub based *
- * on the change in length. *
- * *
- *************************************************************/
-
- static float Track_AmountToRotateNubs(TrackSectionType *trackSectionList,
- long numTrackSections,
- NubEntryType *coordPtr,
- long numNubsInPart,
- long sectionNum,
- float *scale)
- {
- TQ3Vector3D startVec,endVec,originalVec,desiredVec;
- long i;
- float rotation,originalSize,desiredSize;
- TQ3Point3D originalPt,desiredPt,zeroPt = {0,0,0};
-
-
- /* CALC ORIGINAL VECTOR */
-
-
- startVec.x = coordPtr[1].basePt.x; /* use 2nd nub as start coord (remember that we skip the 1st nub in a part) */
- startVec.y = coordPtr[1].basePt.y;
- startVec.z = coordPtr[1].basePt.z;
- endVec.x = coordPtr[numNubsInPart-1].basePt.x; /* use last nub as end coord of original data */
- endVec.y = coordPtr[numNubsInPart-1].basePt.y;
- endVec.z = coordPtr[numNubsInPart-1].basePt.z;
- Q3Vector3D_Subtract(&endVec,&startVec,&originalVec); /* calc vector from start to end */
-
- /* CALC DESIRED VECTOR */
-
- i = sectionNum+1;
- if (i >= numTrackSections)
- {
- i = 0;
- }
- startVec.x = trackSectionList[sectionNum].nubCoord.x; /* get vector of where we want it to endup */
- startVec.y = trackSectionList[sectionNum].nubCoord.y;
- startVec.z = trackSectionList[sectionNum].nubCoord.z;
- endVec.x = trackSectionList[i].nubCoord.x; /* get vector of where we want it to endup */
- endVec.y = trackSectionList[i].nubCoord.y;
- endVec.z = trackSectionList[i].nubCoord.z;
- Q3Vector3D_Subtract(&endVec,&startVec,&desiredVec); /* calc vector from start to desired end */
-
- /* CALC ANGLE */
-
- rotation = Utils_AngleBetweenVectors(originalVec,desiredVec); /* calc amount we need to rotate all nubs in part */
- if (desiredVec.z > originalVec.z) /* see if need to negate (since we only have absolute angle between vecs) */
- {
- rotation = -rotation;
- }
-
- /* CALC SCALING TO ADJUST FOR DISTANCE CHANGE */
-
- originalPt.x = originalVec.x; /* calc size of original segment */
- originalPt.y = originalVec.y;
- originalPt.z = originalVec.z;
- originalSize = Q3Point3D_Distance(&originalPt,&zeroPt);
-
- desiredPt.x = desiredVec.x; /* calc size of desired seg */
- desiredPt.y = desiredVec.y;
- desiredPt.z = desiredVec.z;
- desiredSize = Q3Point3D_Distance(&desiredPt,&zeroPt);
-
- *scale = desiredSize/originalSize; /* return scaling value */
-
- return(rotation);
- }
-
-
- #if TARGET_OS_WIN32
-
- /************************************************************
- * *
- * FUNCTION: Track_LoadPartsFromFile *
- * *
- * PURPOSE: Loads our pre-generated track parts *
- * from a file *
- * *
- *************************************************************/
-
- void Track_LoadPartsFromFile(PartType *partsList, short *partCount)
-
- {
- HANDLE fileHndl;
- DWORD err;
- char partFilePath[MAX_PATH];
-
-
- err = Utils_Win32_BuildCurDirPath((Ptr)&partFilePath, kPartDataFileName);
- fileHndl = CreateFile((char *)&partFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
- if ((fileHndl == NULL) || (fileHndl == INVALID_HANDLE_VALUE))
-
- {
-
- Utils_DisplayFatalErrorMsg("Failure loading track part file TrackPartData.dat!");
-
- }
-
- else
-
- {
- Ptr currentIndex;
- HLOCAL localMem;
- DWORD numBytesRead, fileSize;
- BOOL successfull = FALSE;
-
-
- fileSize = GetFileSize(fileHndl, NULL);
- localMem = LocalAlloc(LMEM_FIXED, fileSize);
- if (localMem != NULL)
- {
- currentIndex = localMem;
- *partCount = 0;
- successfull = FALSE;
-
-
- do
- {
- /* get count of nubs for this part */
-
- successfull = ReadFile(fileHndl, &partsList[*partCount].numNubs, sizeof(partsList->numNubs), &numBytesRead, NULL);
- if ((successfull == TRUE) && (numBytesRead != 0))
- {
- numBytesRead = 0;
- successfull = ReadFile(fileHndl, currentIndex, sizeof(NubEntryType) * partsList[*partCount].numNubs, &numBytesRead, NULL);
- if ((successfull == TRUE) && (numBytesRead != 0))
- {
- /* SAVE PART RECORD */
- partsList[*partCount].coordsPtr = (NubEntryType *)currentIndex;
- /* move pointer to point to memory for next part */
- currentIndex = currentIndex + sizeof(NubEntryType) * partsList[*partCount].numNubs;
- ++ (*partCount);
- }
- else
- {
- Utils_DisplayFatalErrorMsg("Error reading track part file TrackPartData.dat!");
-
- }
- }
- }
- while ((successfull == TRUE) && (numBytesRead != 0));
- }
- else
- {
- Utils_DisplayFatalErrorMsg("Memory allocation failure!");
-
- }
- }
- }
-
-
- #endif
-
-
-
-
- /************************************************************
- * *
- * FUNCTION: Track_LoadPartsFromRez *
- * *
- * PURPOSE: Loads our pre-generated track parts *
- * from a resource file *
- * *
- *************************************************************/
-
-
- #if TARGET_OS_MAC
-
-
- void Track_LoadPartsFromRez(PartType *partsList, short *partCount)
- {
- OSErr err;
- short i;
- Handle partHandle;
- PartType *thisPart;
- Byte numNubs;
- Ptr nubCoordsPtr;
-
-
- *partCount = 0;
-
- /* get count of part resources in our resource file */
- *partCount = Count1Resources(kPartType);
- err = ResError();
- if (err != noErr)
- {
- Utils_DisplayFatalErrorMsg("Error Getting Part Resource");
- }
- else
- {
- for (i = 1; i <= *partCount; i++)
- {
- /* get next part resource in our file */
- partHandle = GetIndResource(kPartType,i);
- if (partHandle == nil)
- {
- Utils_DisplayFatalErrorMsg("Error Getting Part Resource");
- }
- else
- {
- DetachResource(partHandle); /* give it to me */
- HLockHi(partHandle);
-
- thisPart = (PartType *)(*partHandle);
-
- /* get number of points in this part from the numNubs field of
- the PartType structure */
-
- numNubs = thisPart->numNubs;
-
- /* allocate enough NubEntryType structures to hold all of the points
- in this part */
-
- nubCoordsPtr = NewPtr(sizeof(NubEntryType) * numNubs);// alloc memory for nub coords
- if (nubCoordsPtr == nil)
- {
- Utils_DisplayFatalErrorMsg("Not enough memory to load Part");
- }
- else
- {
- /* copy NubEntryType data to our memory block */
- //BlockMove((Ptr)&thisPart->coordsPtr,nubCoordsPtr,sizeof(NubEntryType) * numNubs);
- BlockMove((Ptr)thisPart + sizeof(thisPart->numNubs),nubCoordsPtr,sizeof(NubEntryType) * numNubs);
- DisposeHandle(partHandle);
-
- /* save part record as a PartType structure */
- partsList[i-1].numNubs = numNubs;
- partsList[i-1].coordsPtr = (NubEntryType *)nubCoordsPtr;
-
- }
- }
- }
- }
- }
-
-
- #endif
-
-
- /************************************************************
- * *
- * FUNCTION: Track_PutCameraOnTrack *
- * *
- * PURPOSE: Calculates placement of the camera on the *
- * track *
- * *
- * *
- * *
- *************************************************************/
-
- void Track_PutCameraOnTrack(TQ3CameraObject camera,
- NubEntryType *splinePtArray,
- long numSplinePoints,
- long curTrackLocation
- )
- {
- TQ3Point3D cameraFrom,cameraTo;
- TQ3Vector3D cameraUp,cameraFromVect;
- long desti;
- TQ3CameraPlacement placement;
-
-
- if (numSplinePoints == 0)
- return;
-
-
- /* CALC UP VECTOR */
-
- Q3Point3D_Subtract(&splinePtArray[curTrackLocation].upPt, /* calc vector from base to up point */
- &splinePtArray[curTrackLocation].basePt,
- &cameraUp);
- Q3Vector3D_Normalize(&cameraUp,&cameraUp);
-
-
- /* USE UP VECTOR TO CALC "FROM" POSITION */
-
- Q3Vector3D_Scale(&cameraUp,DISTANCE_FROM_TRACK_TO_CAMERA,&cameraFromVect); /* calc how far above track to put camera */
- cameraFrom.x = (splinePtArray[curTrackLocation].basePt.x +
- cameraFromVect.x);
- cameraFrom.y = (splinePtArray[curTrackLocation].basePt.y +
- cameraFromVect.y);
- cameraFrom.z = (splinePtArray[curTrackLocation].basePt.z +
- cameraFromVect.z);
-
- /* SET "TO" PT */
-
- desti = curTrackLocation + kSkipAheadPoints;
- if (desti >= (numSplinePoints-1))
- {
- desti -= numSplinePoints; /* loop back around */
- }
-
- cameraTo = splinePtArray[desti].basePt; /* look at base spline point in distance */
-
-
- /* UPDATE CAMERA PLACEMENT */
-
- placement.cameraLocation = cameraFrom; /* set placement data */
- placement.pointOfInterest = cameraTo;
- placement.upVector = cameraUp;
- Q3Camera_SetPlacement(camera,&placement);
-
- }
-
-
- /************************************************************
- * *
- * FUNCTION: Track_BuildCoasterGeometry_Mesh_Textured *
- * *
- * PURPOSE: Build a textured track using mesh objects *
- * *
- * *
- *************************************************************/
-
- void Track_BuildCoasterGeometry_Mesh(long skipValue,
- TQ3GroupObject theGroup,
- long numSplinePoints,
- NubEntryType *splinePointsPtr)
- {
- TQ3GeometryObject myMesh = NULL;
- TQ3GroupPosition myGroupPosition;
- TQ3ColorRGB whiteColor = {1,1,1};
- long i,faceCount,colorTick = 0;
- float x2,y2,z2;
- TQ3Vector3D tangentVector;
- TQ3MeshVertex meshVertexList[4];
- TQ3Vertex3D vertexList[4],firstLeft,firstRight;
- TQ3AttributeSet generalAttribs = NULL,vAttrib[4] = {NULL, NULL, NULL, NULL};
- TQ3MeshFace face;
- float ambient = 0.8F;
- float spec = 0.0F;
- TQ3Param2D corner1 = {0,1}; /* uv's for texture mapping */
- TQ3Param2D corner2 = {1,1};
- TQ3Param2D corner3 = {1,0};
- TQ3Param2D corner4 = {0,0};
-
-
-
- /* CREATE NEW MESH OBJECT */
-
- myMesh = Q3Mesh_New();
-
- if( myMesh == NULL )
- {
- Utils_DisplayErrorMsg("Group_AddObject failed!");
- goto memoryError;
- }
-
- Q3Mesh_DelayUpdates(myMesh);
-
-
- /* SETUP GENERAL ATTRIBUTES */
-
- generalAttribs = Q3AttributeSet_New();
- if( generalAttribs == NULL )
- {
- Utils_DisplayErrorMsg("Q3AttributeSet_New failed!");
- goto memoryError;
- }
- Q3AttributeSet_Add(generalAttribs, kQ3AttributeTypeAmbientCoefficient, &ambient);
- Q3AttributeSet_Add(generalAttribs, kQ3AttributeTypeSpecularControl, &spec);
-
-
- /* CREATE UV ATTRIBUTES FOR THE VERTICES */
-
- vAttrib[0] = Q3AttributeSet_New();
- if( vAttrib[0] == NULL )
- {
- Utils_DisplayErrorMsg("Q3AttributeSet_New failed!");
- goto memoryError;
- }
- Q3AttributeSet_Add(vAttrib[0], kQ3AttributeTypeShadingUV, &corner1);
-
- vAttrib[1] = Q3AttributeSet_New();
- if( vAttrib[1] == NULL )
- {
- Utils_DisplayErrorMsg("Q3AttributeSet_New failed!");
- goto memoryError;
- }
- Q3AttributeSet_Add(vAttrib[1], kQ3AttributeTypeShadingUV, &corner2);
-
- vAttrib[2] = Q3AttributeSet_New();
- if( vAttrib[2] == NULL )
- {
- Utils_DisplayErrorMsg("Q3AttributeSet_New failed!");
- goto memoryError;
- }
- Q3AttributeSet_Add(vAttrib[2], kQ3AttributeTypeShadingUV, &corner3);
-
- vAttrib[3] = Q3AttributeSet_New();
- if( vAttrib[3] == NULL )
- {
- Utils_DisplayErrorMsg("Q3AttributeSet_New failed!");
- goto memoryError;
- }
- Q3AttributeSet_Add(vAttrib[3], kQ3AttributeTypeShadingUV, &corner4);
-
-
- vertexList[0].attributeSet = nil;
- vertexList[1].attributeSet = nil;
- vertexList[2].attributeSet = nil;
- vertexList[3].attributeSet = nil;
-
- faceCount = 0;
-
-
- for (i = 0; i < (numSplinePoints - 1 - skipValue); i += skipValue)
- {
- /* GET SPLINE POINTS */
-
- x2 = splinePointsPtr[i+skipValue].basePt.x; /* get coords of end pt #2 (far point) */
- y2 = splinePointsPtr[i+skipValue].basePt.y;
- z2 = splinePointsPtr[i+skipValue].basePt.z;
-
-
- /* CALC TANGENT VECTOR */
-
- Q3Point3D_CrossProductTri(&splinePointsPtr[i].basePt,
- &splinePointsPtr[i+skipValue].basePt,
- &splinePointsPtr[i].upPt,&tangentVector);
-
- Q3Vector3D_Normalize(&tangentVector,&tangentVector);
- Q3Vector3D_Scale(&tangentVector,kTrackWidth,&tangentVector);
-
-
- /* CALC NEW "UPPER" COORDS OF FACE */
-
- Q3Point3D_Set(&vertexList[0].point, /* upper left */
- x2-tangentVector.x,
- y2-tangentVector.y,
- z2-tangentVector.z);
-
- Q3Point3D_Set(&vertexList[1].point, /* upper right */
- x2+tangentVector.x,
- y2+tangentVector.y,
- z2+tangentVector.z);
-
-
- meshVertexList[0] = Q3Mesh_VertexNew(myMesh, &vertexList[0]); /* get new vertex for "upper/far" */
- meshVertexList[1] = Q3Mesh_VertexNew(myMesh, &vertexList[1]);
-
-
- /* FOR 1ST FACE, MUST RIG "BOTTOM" COORDS */
-
- if (i == 0)
- {
- Q3Point3D_Set(&vertexList[2].point, /* lower right */
- splinePointsPtr[0].basePt.x+tangentVector.x,
- splinePointsPtr[0].basePt.y+tangentVector.y,
- splinePointsPtr[0].basePt.z+tangentVector.z);
-
- Q3Point3D_Set(&vertexList[3].point, /* lower left */
- splinePointsPtr[0].basePt.x-tangentVector.x,
- splinePointsPtr[0].basePt.y-tangentVector.y,
- splinePointsPtr[0].basePt.z-tangentVector.z);
-
- firstRight.point = vertexList[2].point; /* remember these coords for wrap-back later */
- firstLeft.point = vertexList[3].point;
-
- meshVertexList[2] = Q3Mesh_VertexNew(myMesh, &vertexList[2]); /* set vertex */
- meshVertexList[3] = Q3Mesh_VertexNew(myMesh, &vertexList[3]);
- }
-
-
- /* CREATE FACE */
-
- face = Q3Mesh_FaceNew(myMesh,4,&meshVertexList[0],generalAttribs);
-
- if( face == NULL )
- {
- Utils_DisplayErrorMsg("Q3AttributeSet_New failed!");
- goto memoryError;
- }
-
- /* APPLY UV COORD ATTRIBS */
-
- Q3Mesh_SetCornerAttributeSet(myMesh, meshVertexList[0], face, vAttrib[0]);
- Q3Mesh_SetCornerAttributeSet(myMesh, meshVertexList[1], face, vAttrib[1]);
- Q3Mesh_SetCornerAttributeSet(myMesh, meshVertexList[2], face, vAttrib[2]);
- Q3Mesh_SetCornerAttributeSet(myMesh, meshVertexList[3], face, vAttrib[3]);
-
- colorTick++;
- faceCount++;
-
- /* SEE IF MESH OBJECT IS LARGE ENOUGH TO USE NOW */
-
- if (faceCount > kMaxFacesInMesh)
- {
- Q3Mesh_ResumeUpdates(myMesh);
-
- myGroupPosition = Q3Group_AddObject(theGroup, myMesh); /* add mesh to group */
- Q3Object_Dispose(myMesh); /* make another mesh object */
- if ( myGroupPosition == nil )
- {
- Utils_DisplayErrorMsg("Q3Group_AddObject failed!");
- goto memoryError;
- }
-
- myMesh = Q3Mesh_New();
- if ( myMesh == nil )
- {
- Utils_DisplayErrorMsg("Q3Mesh_New failed!");
- goto memoryError;
- }
- Q3Mesh_DelayUpdates(myMesh);
- meshVertexList[0] = Q3Mesh_VertexNew(myMesh, &vertexList[0]); /* reset these to the new mesh */
- meshVertexList[1] = Q3Mesh_VertexNew(myMesh, &vertexList[1]);
-
- faceCount = 0;
- }
-
- /* UPPERS WILL BE LOWERS ON NEXT POLY */
-
- vertexList[2] = vertexList[1]; /* this is so next poly's bottom will match last poly's top */
- vertexList[3] = vertexList[0];
- meshVertexList[2] = meshVertexList[1];
- meshVertexList[3] = meshVertexList[0];
-
- if (colorTick & 1)
- {
- vertexList[0].attributeSet = vAttrib[0]; /* apply uv attribs to the vertices */
- vertexList[1].attributeSet = vAttrib[1];
- vertexList[2].attributeSet = vAttrib[2];
- vertexList[3].attributeSet = vAttrib[3];
- }
- else
- {
- vertexList[0].attributeSet = vAttrib[3]; /* apply uv attribs to the vertices */
- vertexList[1].attributeSet = vAttrib[2];
- vertexList[2].attributeSet = vAttrib[1];
- vertexList[3].attributeSet = vAttrib[0];
- }
- }
-
- /* CREATE 1 FINAL FACE TO LINK BACK TO BEGINNING */
-
- vertexList[0].point = firstLeft.point;
- vertexList[1].point = firstRight.point;
- meshVertexList[0] = Q3Mesh_VertexNew(myMesh, &vertexList[0]); /* create vertex based on 1st */
- meshVertexList[1] = Q3Mesh_VertexNew(myMesh, &vertexList[1]);
-
- if (faceCount & 1)
- {
- face = Q3Mesh_FaceNew(myMesh,4,&meshVertexList[0],nil);
- }
- else
- {
- face = Q3Mesh_FaceNew(myMesh,4,&meshVertexList[0],nil);
- }
- faceCount++;
-
- /* APPLY ANY REMAINING MESH */
-
- Q3Mesh_ResumeUpdates(myMesh);
-
- if (faceCount > 0)
- {
- myGroupPosition = Q3Group_AddObject(theGroup, myMesh);
- if ( myGroupPosition == nil )
- {
- Utils_DisplayErrorMsg("Q3Group_AddObject failed!");
- goto memoryError;
- }
- }
-
- Q3Object_Dispose(myMesh); /* kill mesh object */
- Q3Object_Dispose(generalAttribs);
- Q3Object_Dispose(vAttrib[0]);
- Q3Object_Dispose(vAttrib[1]);
- Q3Object_Dispose(vAttrib[2]);
- Q3Object_Dispose(vAttrib[3]);
-
- return;
-
- memoryError:
- if( myMesh )
- {
- Q3Object_Dispose(myMesh);
- }
-
- if( generalAttribs )
- {
- Q3Object_Dispose(generalAttribs);
- }
-
- if( vAttrib[0] )
- {
- Q3Object_Dispose(vAttrib[0]);
- }
-
- if( vAttrib[1] )
- {
- Q3Object_Dispose(vAttrib[1]);
- }
-
- if( vAttrib[2] )
- {
- Q3Object_Dispose(vAttrib[2]);
- }
-
- if( vAttrib[3] )
- {
- Q3Object_Dispose(vAttrib[3]);
- }
-
- }
-
-
- /************************************************************
- * *
- * FUNCTION: Track_CalcSplineCurve *
- * *
- * PURPOSE: Use our control points to construct a *
- * spline curve for each section of the *
- * track *
- * *
- * *
- *************************************************************/
-
- void Track_CalcSplineCurve(NubEntryType **splinePoints,
- long maxSplinePoints,
- NubEntryType *nubPoints,
- long numSplineNubs,
- long *numSplinePoints,
- float subDivFactor)
- {
- float t,tSquared,tCubed,a,b,c,d,incVal;
- long subCount,nubNum,numNubs,numSubDivs;
- TQ3Point3D highestPoint = {0,0,0};
-
- /* ALLOC MEMORY FOR SPLINE DATA */
-
- *splinePoints = (NubEntryType *)NewPtr( sizeof(NubEntryType) * maxSplinePoints );
- if (*splinePoints == nil)
- {
- Utils_DisplayFatalErrorMsg("Sorry, but there doesnt seem to be enough memory to allocate the track spline curve");
- }
- else
- {
-
- numNubs = numSplineNubs; /* # nubs */
- *numSplinePoints = 0; /* # points generated */
-
- /* SCAN THRU NUBS */
-
- /* Note: skips 1st & last nubs (sorta) */
- for (nubNum=1; nubNum < (numNubs-2); nubNum++)
- {
- numSubDivs = Q3Point3D_Distance(&nubPoints[nubNum].basePt,
- &nubPoints[nubNum+1].basePt)*subDivFactor + 0.5F; /* # segments between next nubs */
- if (numSubDivs < 1)
- numSubDivs = 1;
-
- incVal = 1.0F/numSubDivs; /* increment value */
-
- for (t=0, subCount=0; subCount < numSubDivs; t+=incVal,subCount++)
- {
- tSquared = t*t;
- tCubed = tSquared*t;
- a = (-0.166F * tCubed)+(0.5F * tSquared)-(0.5F * t) + 0.166F;
- b = (0.5F * tCubed) - tSquared + 0.666F;
- c = (-0.5F * tCubed) + (0.5F * tSquared) + (0.5F * t + 0.166F);
- d = 0.166F * tCubed;
-
- if (*numSplinePoints < maxSplinePoints)
- {
- /* CALC SEG OF BASE */
-
- (*splinePoints)[*numSplinePoints].basePt.x =
- (a * nubPoints[nubNum-1].basePt.x) +
- (b * nubPoints[nubNum].basePt.x) +
- (c * nubPoints[nubNum+1].basePt.x) +
- (d * nubPoints[nubNum+2].basePt.x);
-
- (*splinePoints)[*numSplinePoints].basePt.y =
- (a * nubPoints[nubNum-1].basePt.y) +
- (b * nubPoints[nubNum].basePt.y) +
- (c * nubPoints[nubNum+1].basePt.y) +
- (d * nubPoints[nubNum+2].basePt.y);
-
- (*splinePoints)[*numSplinePoints].basePt.z =
- (a * nubPoints[nubNum-1].basePt.z) +
- (b * nubPoints[nubNum].basePt.z) +
- (c * nubPoints[nubNum+1].basePt.z) +
- (d * nubPoints[nubNum+2].basePt.z);
-
- /* CALC SEG OF UP */
-
- (*splinePoints)[*numSplinePoints].upPt.x =
- (a * nubPoints[nubNum-1].upPt.x) +
- (b * nubPoints[nubNum].upPt.x) +
- (c * nubPoints[nubNum+1].upPt.x) +
- (d * nubPoints[nubNum+2].upPt.x);
-
- (*splinePoints)[*numSplinePoints].upPt.y =
- (a * nubPoints[nubNum-1].upPt.y) +
- (b * nubPoints[nubNum].upPt.y) +
- (c * nubPoints[nubNum+1].upPt.y) +
- (d * nubPoints[nubNum+2].upPt.y);
-
- (*splinePoints)[*numSplinePoints].upPt.z =
- (a * nubPoints[nubNum-1].upPt.z) +
- (b * nubPoints[nubNum].upPt.z) +
- (c * nubPoints[nubNum+1].upPt.z) +
- (d * nubPoints[nubNum+2].upPt.z);
-
- /* REMEMBER WHAT TYPE IT IS */
-
- (*splinePoints)[*numSplinePoints].sectionNum = nubPoints[nubNum].sectionNum;
-
- (*numSplinePoints)++;
- }
- else
- {
- Utils_DisplayFatalErrorMsg("Too many spline points! Overflowed array!");
- }
- }
- }
- }
- }
-
- /************************************************************
- * *
- * FUNCTION: Track_MoveCamera *
- * *
- * PURPOSE: Move the camera to the next location on the *
- * track *
- * *
- * *
- *************************************************************/
-
- void Track_MoveCamera(TQ3CameraObject camera,
- NubEntryType *splinePtArray,
- long numSplinePoints,
- long *curTrackLocation)
- {
- Track_PutCameraOnTrack(camera,
- splinePtArray,
- numSplinePoints,
- *curTrackLocation);
- /* have we reached the end of the track? */
- if ( ((*curTrackLocation) + 1) >= numSplinePoints)
- {
- /* end-of-track, so wrap back to the beginning */
- (*curTrackLocation) = 0;
- }
- else
- {
- /* move to next location on track */
- ++(*curTrackLocation);
- }
-
- }
-
-
- /************************************************************
- * *
- * FUNCTION: Track_GetForwardVector *
- * *
- * PURPOSE: Returns the vector representing forward at *
- * trackIndex *
- * *
- * *
- *************************************************************/
-
- void Track_GetForwardVector(long trackIndex, NubEntryType *splinePointsPtr, long numSplinePoints, TQ3Vector3D *theVector)
- {
- TQ3Vector3D forward;
-
- if ((trackIndex+1) == numSplinePoints) /* see if +1 will wrap it */
- Q3Point3D_Subtract(&splinePointsPtr[0].basePt, /* calc vector from here to one in front */
- &splinePointsPtr[trackIndex].basePt,
- &forward);
- else
- Q3Point3D_Subtract(&splinePointsPtr[trackIndex+1].basePt, /* calc vector from here to one in front */
- &splinePointsPtr[trackIndex].basePt,
- &forward);
- Q3Vector3D_Normalize(&forward,theVector); /* normalize & return it */
- }
-
-
- /************************************************************
- * *
- * FUNCTION: Track_GetNormalVector *
- * *
- * PURPOSE: Returns the vector to the normal of the *
- * surface of the track at trackIndex *
- * *
- * *
- *************************************************************/
-
- void Track_GetNormalVector(NubEntryType *splinePointsPtr, long trackIndex, TQ3Vector3D *theVector)
- {
- TQ3Vector3D cameraUp;
-
- Q3Point3D_Subtract(&splinePointsPtr[trackIndex].upPt, /* calc vector from base to up point */
- &splinePointsPtr[trackIndex].basePt,
- &cameraUp);
- Q3Vector3D_Normalize(&cameraUp,theVector); /* normalize & return it */
- }
-
-